package com.java.redis;

import com.sun.xml.internal.ws.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.ArrayList;
import java.util.Collections;

public class RedisDistributedLock implements DistributedLock{
    private JedisPool jedisPool;
    private String lockKey;
    private String requestId;
    private int expireTime;

    public  RedisDistributedLock(JedisPool jedisPool, String lockKey, String requestId, int expireTime){
        this.jedisPool = jedisPool;
        this.lockKey = lockKey;
        this.requestId = requestId;
        this.expireTime = expireTime;
    }

    //requestId必须是唯一，否则会导致因为受阻塞的key失效重启时使得重新获取锁的失效
    public boolean tryLock(){
        //验证参数
        validParam(jedisPool, lockKey, requestId, expireTime);
        Jedis jedis = null;
        try{
            //判断lockKey是否存在
            String lua_scripts = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then " +
                    "redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";
            jedis = jedisPool.getResource();
            ArrayList<String> keys = new ArrayList<>();
            ArrayList<String> values = new ArrayList<>();
            keys.add(lockKey);
            values.add(requestId);
            values.add(String.valueOf(expireTime));
            Object result = jedis.eval(lua_scripts, keys, values);
            return result.equals(1L);
        }catch (Exception e){
            throw e;
        }finally {
            if (jedis != null){
                jedis.close();
            }
        }
    }

    @Override
    public boolean lock() {

        return false;
    }

    private void validParam(JedisPool jedisPool, String lockKey, String requestId, int expireTime) {
        if (jedisPool == null){
            throw new IllegalArgumentException("JedisPoll is null");
        }

        if (lockKey == null || lockKey.equals("")){
            throw new IllegalArgumentException("lock key is bank");
        }

        if (requestId == null || requestId.equals("")){
            throw new IllegalArgumentException("request id is bank");
        }

        if (expireTime < 0){
            throw new IllegalArgumentException("expire time is not allowed less zero");
        }
    }

    @Override
    public boolean unLock() {
        String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then " +
                "return redis.call('del',KEYS[1]) else return 0 end";
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Object result = jedis.eval(luaScript, Collections.singletonList(lockKey), Collections.singletonList(requestId));
            return result.equals(1L);
        }catch (Exception e){
            throw e;
        }finally {
            jedis.close();
        }
    }
}
